package codeoffloading;

import java.util.HashMap;

import netcom.NetManager;
import netcom.messages.ExecutionReplyMessage;
import netcom.messages.ExecutionRequestMessage;
import codeoffloading.profiling.Profiler;

public class CodeOffloadingManager {

	private static CodeOffloadingManager instance = null;
	private static int callIds = 0;
	//call id as index
	private HashMap<Integer, PendingMethod> pendingM;
	
	
	public static CodeOffloadingManager getInstance(){
		if(instance == null){
			System.err.println("MAUI For Android  ins't setup corretly on the device");
		}
		return instance;
	}
	
	public static void setup(){
		System.out.println("MAUI for Android Setup");
		if(NetManager.getInstance().isRunning()){
			System.out.println("\tNetwork Setup Corretly");
		}
		instance = new CodeOffloadingManager();
	}
	
	
	
	private CodeOffloadingManager(){
		pendingM = new HashMap<Integer, PendingMethod>();
	}
	
	
	
	public void executeMethodRemotely(String methodName, ClassStub stub, Object[] paramas){
		//generate callId
		callIds++;
		
		if(callIds == Integer.MAX_VALUE) callIds = 0;
		
		int callId = callIds;
		
		PendingMethod m = new PendingMethod();
		m.setCallId(callId);
		m.setMethodName(methodName);
		m.setParamas(paramas);
		m.setStub(stub);
		
		synchronized(this){
			pendingM.put(callId, m);
		}
		
	
		ExecutionRequestMessage exReq = new ExecutionRequestMessage(callIds, stub.classInstance, methodName, paramas);
		NetManager.getInstance().askForServiceExecution(exReq);
	}
	
	
	
	public void methodResults(ExecutionReplyMessage m){
		PendingMethod met = pendingM.get(m.getExecutionId());
		met.getStub().setClassInstance(m.getCla());
		pendingM.remove(met);
		met.getStub().remoteResultsAreComed(m.getResults());
	}
	
	
	
	
	public class PendingMethod{
		
		private int callId;
		private String methodName;
		private ClassStub stub;
		private Object[] paramas;
		
		public int getCallId() {return callId;}
		public void setCallId(int callId) { this.callId = callId; }
		public String getMethodName() { return methodName;}
		public void setMethodName(String methodName) { this.methodName = methodName; }
		public ClassStub getStub() { return stub; }
		public void setStub(ClassStub stub) { this.stub = stub; }
		public Object[] getParamas() { return paramas; }
		public void setParamas(Object[] paramas) { this.paramas = paramas;}
		
		
		
		
		
	}

	
	
}
